package project;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import javax.imageio.ImageIO;

public class IOUtilities
{
  private static final byte[] BUFFER_8192 = new byte[8192];

  private static final FileFilter fileFileFilter = new FileFileFilter();

  private static final FileFilter directoryFileFilter = new DirectoryFileFilter();

  public static String extractFileWithoutPath(String filePath)
  {
    if (filePath.endsWith(File.separator))
    {
      int l = filePath.length();

      filePath = filePath.substring(0, l - 1);
    }

    int i = filePath.lastIndexOf(File.separator);

    return filePath.substring(i + 1);
  }

  public static String getFileExtension(File f)
  {
    return getFileExtension(f.getName());
  }

  public static String getFileExtension(String file)
  {
    String ext = null;

    int i = file.lastIndexOf('.');

    if ((i > 0) && (i < file.length() - 1))
    {
      ext = file.substring(i).toLowerCase();
    }

    return ext;
  }

  public static int countFiles(File file)
    throws IOException
  {
    return privateCount(file, false);
  }

  public static int recursivelyCountFiles(File file)
    throws IOException
  {
    return privateCount(file, true);
  }

  private static int privateCount(File file, boolean rec)
    throws IOException
  {
    if (!file.exists())
    {
      String m = "'" + file.getAbsolutePath() + "' does not exist!";

      throw new IOException(m);
    }

    if (file.isFile())
    {
      return 1;
    }

    File[] files = file.listFiles(new FileFileFilter());

    if (!rec)
    {
      return files.length;
    }

    File[] dirs = file.listFiles(new DirectoryFileFilter());

    int recCounter = files.length;

    for (int ctr = 0; ctr < dirs.length; ++ctr)
    {
      recCounter += privateCount(dirs[ctr], true);
    }

    return recCounter;
  }

  public static byte[] convertBufferedImageToByteArray(BufferedImage image, String format)
    throws IOException
  {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();

    ImageIO.write(image, format, bos);

    return bos.toByteArray();
  }

  public static byte[] getBytesFromInputStream(InputStream stream)
    throws IOException
  {
    int bytesRead = 0;

    ByteArrayOutputStream bos = new ByteArrayOutputStream();

    while ((bytesRead = stream.read(BUFFER_8192)) != -1)
    {
      bos.write(BUFFER_8192, 0, bytesRead);
    }

    return bos.toByteArray();
  }

  public static void copy(String sourcePath, String destPath)
    throws IOException
  {
    copy(sourcePath, destPath, false);
  }

  public static void copy(String sourcePath, String destPath, boolean overwriteOK)
    throws IOException
  {
    copy(new File(sourcePath), new File(destPath), overwriteOK);
  }

  public static void copy(File sourceFile, File destFile)
    throws IOException
  {
    copy(sourceFile, destFile, false);
  }

  public static void copy(File sourceFile, File destFile, boolean overwriteOK)
    throws IOException
  {
    if (!sourceFile.exists())
    {
      throw new IOException("The file '" + sourceFile.getName() + "' does not exist!");
    }

    if (!sourceFile.isFile())
    {
      throw new IOException("The file '" + sourceFile.getName() + "' is not a file!");
    }

    copy(new FileInputStream(sourceFile), destFile, overwriteOK);
  }

  public static void copy(InputStream input, File destFile)
    throws IOException
  {
    copy(input, destFile, false);
  }

  public static void copy(InputStream input, File destFile, boolean overwriteOK)
    throws IOException
  {
    if ((destFile.exists()) && (!overwriteOK))
    {
      throw new IOException("The file '" + destFile.getName() + "' already exists!");
    }

    if (!destFile.getParentFile().exists())
    {
      destFile.getParentFile().mkdirs();
    }

    destFile.createNewFile();

    copy(input, new FileOutputStream(destFile));
  }

  public static void copy(InputStream input, OutputStream output)
    throws IOException
  {
    copy(input, output, true, true);
  }

  public static void copy(InputStream input, OutputStream output, boolean closeIn, boolean closeOut)
    throws IOException
  {
    int bytesRead = 0;

    while ((bytesRead = input.read(BUFFER_8192)) != -1)
    {
      output.write(BUFFER_8192, 0, bytesRead);
    }

    if (closeIn)
    {
      input.close();
    }

    if (!closeOut)
      return;
    output.close();
  }

  public static Object serialClone(Serializable obj)
    throws IOException, ClassNotFoundException
  {
    ByteArrayOutputStream bout = new ByteArrayOutputStream();

    ObjectOutputStream out = new ObjectOutputStream(bout);

    out.writeObject(obj);

    out.close();

    ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());

    ObjectInputStream in = new ObjectInputStream(bin);

    Object ret = in.readObject();

    in.close();

    return ret;
  }

  public static String[] getRecognizedFileSeparators()
  {
    return new String[] { "\\", "/" };
  }

  public static class DirectoryFileFilter
    implements FileFilter
  {
    public boolean accept(File pathName)
    {
      return pathName.isDirectory();
    }
  }

  public static class FileFileFilter
    implements FileFilter
  {
    public boolean accept(File pathName)
    {
      return pathName.isFile();
    }
  }
}